<!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">








<title>解除具体依赖的技术 - 张逸:晴窗笔记 - 博客园</title>
<meta name="keywords" content="Design,Pattern,解除具体依赖的技术">




<link title="RSS" type="application/rss+xml" rel="alternate" href="http://www.cnblogs.com/wayfarer/rss">
<link title="RSD" type="application/rsd+xml" rel="EditURI" href="http://www.cnblogs.com/wayfarer/rsd.xml"> 
  





<link rel="stylesheet" type="text/css" href="index.css" media="all">
</head>
<body>
    <form name="Form1" method="post" action="http://www.cnblogs.com/wayfarer/archive/2009/11/10/1600467.html" id="Form1">
<div>
<input name="__EVENTTARGET" id="__EVENTTARGET" value="" type="hidden">
<input name="__EVENTARGUMENT" id="__EVENTARGUMENT" value="" type="hidden">
<input name="__VIEWSTATE" id="__VIEWSTATE" value="" type="hidden">
</div>




        <div id="blogtopad">

<ins style="border: medium none ; margin: 0pt; padding: 0pt; display: inline-table; height: 60px; position: relative; visibility: visible; width: 468px;"><ins style="border: medium none ; margin: 0pt; padding: 0pt; display: block; height: 60px; position: relative; visibility: visible; width: 468px;"><iframe allowtransparency="true" hspace="0" id="google_ads_frame1" marginheight="0" marginwidth="0" name="google_ads_frame" src="index_1.html" style="left: 0pt; position: absolute; top: 0pt;" vspace="0" scrolling="no" frameborder="0" height="60" width="468"></iframe></ins></ins>
</div>
			<div id="header">
<h1><a id="Header1_HeaderTitle" class="headermaintitle" href="http://www.cnblogs.com/wayfarer/">张逸:晴窗笔记</a></h1>
<p id="tagline"><!--end  版权保护 -->
<a rel="license" href="http://creativecommons.org/licenses/by-nc-nd/2.5/cn/"><img alt="Creative Commons License" style="border-width: 0pt;" src="88x31.png"></a>
<!-- 版权保护 --></p></div>
			<div id="main">
				
					
	<div class="post">
		<h2>
			<a id="ctl04_TitleUrl" href="http://www.cnblogs.com/wayfarer/archive/2009/11/10/1600467.html">解除具体依赖的技术</a>
		</h2>
		<div class="postText"><p class="MsoNormal" style="margin-bottom: 6pt; text-indent: 21pt;"><span style="font-family: 宋体;" lang="ZH-CN">一个外部具体对象的引入，必然会给一个模块带来与外部模块之间的依赖。而具体对象的创建始终是我们无法规避的。即使我们可以利用设计模式的工厂方法模式或抽象工厂封装具体对象创建的逻辑，但却又再次引入了具体工厂对象的创建依赖。虽然在设计上有所改进，但没有彻底解除具体依赖，仍让我心有戚戚焉。</span></p>  <p class="MsoNormal" style="margin-bottom: 6pt; text-indent: 21pt;"><span style="font-family: 宋体;" lang="ZH-CN">以一个电子商务网站的设计为例。在该项目中要求对客户的订单进行管理，例如插入订单。考虑到访问量的关系，系统为订单管理提供了同步和异步的方式。显然，在实际应用中，我们需要根据具体的应用环境，决定使用这两种方式的其中一种。由于变化非常频繁，因而我们采取了“封装变化”的设计思想。譬如，考虑应用</span>Strategy<span style="font-family: 宋体;" lang="ZH-CN">模式，因为插入订单的行为，实则就是一种插入订单的策略。我们可以为此策略建立抽象对象，如</span>IOrderStrategy<span style="font-family: 宋体;" lang="ZH-CN">接口。</span></p>  <p class="a1">public interface IOrderStrategy</p>  <p class="a1">{</p>  <p class="a1"><span>&nbsp;&nbsp; </span>void Insert(OrderInfo order);</p>  <p class="a1">}</p>  <p class="a3" style="margin: 6pt 0in;"><span style="font-family: 宋体;" lang="ZH-CN">然后分别定义两个类</span>OrderSynchronous<span style="font-family: 宋体;" lang="ZH-CN">和</span>OrderAsynchronous<span style="font-family: 宋体;" lang="ZH-CN">实现</span>IOrderStrategy<span style="font-family: 宋体;" lang="ZH-CN">接口。类结构如图</span>1<span style="font-family: 宋体;" lang="ZH-CN">所示。</span></p>  <p class="a" style="margin: 12pt 0in 0.05in;" align="center"><img title="image" style="border-width: 0px; display: block; float: none; margin-left: auto; margin-right: auto;" alt="image" src="image_3.png" border="0" height="259" width="381">&nbsp;<span style="font-family: 宋体;" lang="ZH-CN">图</span>1<span>&nbsp; </span><span style="font-family: 宋体;" lang="ZH-CN">订单策略的设计</span></p>  <p class="MsoNormal" style="margin-bottom: 6pt; text-indent: 21pt;"><span style="font-family: 宋体;" lang="ZH-CN">当领域对象</span>Order<span style="font-family: 宋体;" lang="ZH-CN">类需要插入订单时，将根据</span>IOrderStrategy<span style="font-family: 宋体;" lang="ZH-CN">接口的运行期类型，执行相关的订单插入策略，如下代码所示。</span></p>  <p class="a1">public class Order</p>  <p class="a1">{</p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp; </span>private IOrderStrategy m_orderStrategy;</p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp; </span>public Order(IOrderStrategy orderStrategy)</p>  <p class="a1"><span>&nbsp;&nbsp; </span>{</p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>m_orderStrategy = orderStrategy;</p>  <p class="a1"><span>&nbsp;&nbsp; </span>}</p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp;&nbsp; </span>public void Insert(OrderInfo order)</p>  <p class="a1"><span>&nbsp;&nbsp; </span>{</p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>m_orderStrategy.Insert(order);</p>  <p class="a1"><span>&nbsp;&nbsp; </span>}</p>  <p class="a1" style="margin-bottom: 6pt;">}</p>  <p class="MsoNormal" style="margin-bottom: 6pt; text-indent: 21pt;"><span style="font-family: 宋体;" lang="ZH-CN">由于用户随时都可能会改变插入订单的策略，因此对于业务层的订单领域对象而言，绝不能与具体的订单策略对象产生耦合关系。也就是说，在领域对象</span>Order<span style="font-family: 宋体;" lang="ZH-CN">类中，不能</span>new<span style="font-family: 宋体;" lang="ZH-CN">一个具体的订单策略对象，如下面的代码：</span></p>  <p class="a1">IOrderStrategy orderStrategy = new OrderSynchronous();</p>  <p class="a3" style="margin: 6pt 0in;"><span style="font-family: 宋体;" lang="ZH-CN">虽然在前面的实现中，我们通过领域对象的构造函数传递了</span>IOrderStrategy<span style="font-family: 宋体;" lang="ZH-CN">接口对象。但这样的实现仅仅是将具体订单策略对象的创建推迟到了领域对象的调用者那里而已，调用者无法避免具体订单策略对象的创建。显然，这是一种“治标不治本”的做法。我们当然也期望能够有一种理想的状态，就是具体对象的创建永远都不要在代码中出现。事实上，模块与模块间之所以产生依赖关系，正是因为有具体对象的存在。一旦在一个模块中创建了另一个模块中的具体对象，依赖就产生了。现在，我们的目的就是要将这些依赖消除。</span></p>  <p class="MsoNormal"><strong>1</strong><strong><span style="font-family: 宋体;" lang="ZH-CN">、配置文件与反射技术</span> </strong></p> <p class="MsoNormal" style="margin-bottom: 6pt; text-indent: 21pt;"><span style="font-family: 宋体;" lang="ZH-CN">使用硬编码方式创建一个对象，必然会带来对象之间的具体依赖。一种最简单的方式是将反射技术与配置文件相结合，在具体对象拥有共同抽象的前提下，通过配置文件获得具体对象的类型信息，然后利用反射创建相应的对象。例如，在领域对象</span>Order<span style="font-family: 宋体;" lang="ZH-CN">类中，可以如此实现：</span></p>  <p class="a1">public class Order</p>  <p class="a1">{</p>  <p class="a1"><span>&nbsp;&nbsp; </span>private static readonly IOrderStrategy orderInsertStrategy =</p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp; </span><span>&nbsp;&nbsp;&nbsp; </span>LoadInsertStrategy();</p>  <p class="a1"><span>&nbsp;&nbsp; </span>private static IOrderStrategy LoadInsertStrategy() </p>  <p class="a1"><span>&nbsp;&nbsp; </span>{</p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp; </span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>//<span style="font-family: 宋体;" lang="ZH-CN">通过配置文件找到具体的订单策略对象</span></p>        <p><span style="letter-spacing: -0.4pt;"><span>&nbsp;&nbsp;&nbsp; </span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>&nbsp;&nbsp;&nbsp; </span>string path = ConfigurationManager.AppSettings["OrderStrategyAssembly"];</span> <br></p>              <p><span style="letter-spacing: -0.5pt;"><span>&nbsp;&nbsp;&nbsp; </span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>&nbsp;&nbsp;&nbsp; </span>string className = ConfigurationManager.AppSettings["OrderStrategyClass"];</span> <br></p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>&nbsp;&nbsp;&nbsp;&nbsp; </span><span>&nbsp;</span>//<span style="font-family: 宋体;" lang="ZH-CN">通过反射创建对象实例</span></p>        <p><span style="letter-spacing: -0.2pt;"><span>&nbsp;&nbsp;&nbsp; </span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>&nbsp; </span>return (IOrderStrategy)Assembly.Load(path).CreateInstance(className);</span> <br></p>  <p class="a1"><span>&nbsp;&nbsp; </span>}</p>  <p class="a1">}</p>  <p class="a2" style="margin: 6pt 0in;"><span style="font-family: 宋体;" lang="ZH-CN">在配置文件</span>web.config<span style="font-family: 宋体;" lang="ZH-CN">中，配置如下的节：</span></p>  <p class="a1">&lt;add key="OrderStrategyAssembly" value="AgileDon.BLL"/&gt;</p>  <p class="a1">&lt;add key="OrderStrategyClass" <span>&nbsp;&nbsp;&nbsp; </span>value="BLL.OrderSynchronous"/&gt;</p>  <p class="a3" style="margin: 6pt 0in;"><span style="font-family: 宋体;" lang="ZH-CN">通过引入泛型，我们可以对前面的逻辑进行有效的封装，例如定义如下的工厂辅助类。</span></p>  <p class="a1">public static class FactoryHelper&lt;T&gt;</p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp; </span>where T:class</p>  <p class="a1">{</p>        <p><span>&nbsp;&nbsp;&nbsp; </span>private static T instance = null; <br></p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp; </span>public static T Create(string typeNameKey, </p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>string nameSpace, </p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>string assemblyPath)</p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp; </span>{</p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>if (instance == null)</p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>string typeName = <span style="letter-spacing: -0.4pt;">ConfigurationManager.AppSettings</span>[typeNameKey];</p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>string className = nameSpace + "." + typeName;</p>  <p class="a1"></p>  <p>&nbsp;</p>  <p>&nbsp;</p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>instance = (T)Assembly.Load(assemblyPath).</p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>CreateInstance(className);</p>        <p><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>} <br></p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>return instance;</p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp; </span>}</p>  <p class="a1">}</p>  <p class="a3" style="margin: 6pt 0in;"><span style="font-family: 宋体;" lang="ZH-CN">注意，</span> Create()<span style="font-family: 宋体;" lang="ZH-CN">辅助方法中的</span>typeNameKey<span style="font-family: 宋体;" lang="ZH-CN">，是指向具体对象类型的键值。通常建议将其键值赋值为具体对象类型的抽象接口类型名，而对应的值则是目标创建对象的类型名。例如：</span></p>  <p class="a1">&lt;add key="<span style="letter-spacing: -0.4pt;">IOrderStrategy</span>" <span>&nbsp;&nbsp; </span>value="OrderSynchronous"/&gt;</p>  <p class="a3" style="margin: 6pt 0in;"><span style="font-family: 宋体;" lang="ZH-CN">然后，我们可以为属于相同命名空间的类统一定义工厂类，并在其中调用工厂辅助类</span>FactoryHelper<span style="font-family: 宋体;" lang="ZH-CN">的</span>Create()<span style="font-family: 宋体;" lang="ZH-CN">辅助方法。例如，为业务逻辑层的对象定义工厂类</span>BLLFactory<span style="font-family: 宋体;" lang="ZH-CN">。</span></p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp; </span>public static class BLLFactory&lt;T&gt;</p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>where T:class</p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp; </span>{</p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>public static T Create(string typeNameKey)</p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>string nameSpace = <span style="letter-spacing: -0.4pt;">ConfigurationManager.AppSettings["BLLAssembly"]</span><span style="font-family: 宋体; letter-spacing: -0.4pt;" lang="ZH-CN">；</span></p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>string assemblyPath = <span style="letter-spacing: -0.4pt;">ConfigurationManager.AppSettings["BLLPath"];</span></p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>return BaseFactory&lt;T&gt;.CreateT(</p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>typeNameKey, nameSpace, assemblyPath);</p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</p>  <p class="a1">}</p>  <p class="MsoNormal" style="margin-bottom: 6pt; text-indent: 21pt;"><span style="font-family: 宋体;" lang="ZH-CN">针对订单策略对象，对应的配置文件为：</span></p>  <p class="a1">&lt;add key="<span style="letter-spacing: -0.4pt;">BLLAssembly</span>" <span>&nbsp;&nbsp;&nbsp;&nbsp; </span>value="AgileDon.BLL"/&gt;</p>  <p class="a1">&lt;add key="<span style="letter-spacing: -0.4pt;">BLLPath</span>" <span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>value="AgileDon.BLL"/&gt;</p>  <p class="a1">&lt;add key="<span style="letter-spacing: -0.4pt;">IOrderStrategy</span>" <span>&nbsp;</span>value="OrderSynchronous"/&gt;</p>  <p class="MsoNormal" style="margin-bottom: 6pt; text-indent: 21pt;"><span style="font-family: 宋体;" lang="ZH-CN">现在，我们就可以调用</span>BLLFactory<span style="font-family: 宋体;" lang="ZH-CN">类的</span>Create ()<span style="font-family: 宋体;" lang="ZH-CN">方法，传入类型名以获得具体的对象。例如：</span></p>  <p class="a1">IOrderStrategy orderInsertStrategy = BLLFactory&lt;IOrderStrategy&gt;.Create(</p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp; </span>"IOrderStrategy");</p>  <p class="a3" style="margin: 6pt 0in;"><span style="font-family: 宋体;" lang="ZH-CN">如果需要将订单插入策略从同步修改为异步方式，只需将配置文件中</span>IOrderStrategy<span style="font-family: 宋体;" lang="ZH-CN">键对应的值修改为</span>"OrderAsynchronous"<span style="font-family: 宋体;" lang="ZH-CN">即可。</span></p>  <p class="MsoNormal"><strong>2</strong><strong><span style="font-family: 宋体;" lang="ZH-CN">、表驱动法</span> </strong></p>        <p class="a3" style="margin: 6pt 0in;"><span style="font-family: 宋体;" lang="ZH-CN">借鉴表驱动法【注：参见</span>Steve McConnell<span style="font-family: 宋体;" lang="ZH-CN">著作《代码大全》第</span>18<span style="font-family: 宋体;" lang="ZH-CN">章】的思想，我们可以利用一个</span>Dictionary<span style="font-family: 宋体;" lang="ZH-CN">集合来维护目标对象与键值之间的映射关系。当我们需要获得对象时，可以利用键值对表进行查询，这样就可以有效地消除</span>if<span style="font-family: 宋体;" lang="ZH-CN">语句。例如，可以在</span>Strategy<span style="font-family: 宋体;" lang="ZH-CN">模式中使用表驱动法，将其作为模式的上下文对象，而不必执行对策略对象类型的逻辑判断。利用表驱动法，我们也可以解除对象之间的具体依赖。</span></p>  <p class="a3" style="margin: 6pt 0in;"><span style="font-family: 宋体;" lang="ZH-CN">仍然以订单的管理为例。我为订单的管理专门定义了一个</span>OrderManager<span style="font-family: 宋体;" lang="ZH-CN">类，它负责初始化并维持对象表。</span></p>  <p class="a1">public static class OrderManager</p>  <p class="a1">{</p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp; </span>private static IDictionary&lt;string,IOrderStrategy&gt; m_strategyTable;</p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp; </span>static OrderManager()</p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp; </span>{</p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Init();</p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp; </span>}</p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp; </span>private static void Init()</p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp; </span>{</p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>m_strategyTable = new Dictionary&lt;string,IOrderStrategy&gt;();</p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>m_strategyTable.Add("sync",new OrderSynchronous());</p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>m_strategyTable.Add("async",new OrderAsynchronous());</p>        <p><span>&nbsp;&nbsp;&nbsp; </span>} <br></p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp; </span>public static IOrderStrategy GetOrderStrategy(string strategyKey)</p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp; </span>{</p>        <p><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>IOrderStrategy strategy; <br></p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>if (m_strategyTable.TryGetValue(strategyKey, out strategy))</p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>return strategy;</p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>else</p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>throw new Exception("<span style="font-family: 宋体;" lang="ZH-CN">无法找到正确的订单策略对象</span>");</p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp; </span>}</p>  <p class="a1">}</p>  <p class="a3" style="margin: 6pt 0in;"><span style="font-family: 宋体;" lang="ZH-CN">在调用</span>OrderManager<span style="font-family: 宋体;" lang="ZH-CN">的</span>GetOrderStrategy()<span style="font-family: 宋体;" lang="ZH-CN">方法时，为提供更好的灵活性，寻找策略对象的键值应该放在配置文件中，以避免修改源代码。</span></p>  <p class="a1">string strategyKey = ConfigurationManager.AppSettings["StrategyKey"]<span style="font-family: 宋体;" lang="ZH-CN">；</span></p>    <p class="MsoNormal" style="margin-bottom: 6pt; text-indent: 21pt;">IOrderStrategy strategy = OrderManager.GetOrderStrategy(strategyKey);<span style="font-family: 宋体;" lang="ZH-CN"><br>我们甚至可以提供一个注册方法</span>RegisterStrategy()<span style="font-family: 宋体;" lang="ZH-CN">，用以应对未来可能的扩展。</span></p>  <p class="a1">public static class OrderManager</p>  <p class="a1">{</p>        <p><span>&nbsp;&nbsp;&nbsp; </span>//<span style="font-family: 宋体;" lang="ZH-CN">其余实现略</span> <br></p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp; </span>public static void RegisterStrategy(</p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>string strategyKey, </p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>IOrderStrategy strategy)</p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp; </span>{</p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>if (String.IsNullOrEmpty(strategyKey))</p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>throw new ArgumentNullException(strategyKey);</p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>if (strategy == null)</p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>throw new ArgumentNullException("<span style="font-family: 宋体;" lang="ZH-CN">策略对象不能为</span>null");</p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>if (m_strategyTable.ContainsKey(strategyKey))</p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>throw new ArgumentException("<span style="font-family: 宋体;" lang="ZH-CN">已经存在键值</span>" + strategyKey);</p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>m_strategyTable.Add(strategyKey,strategy);</p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp; </span>}</p>  <p class="a1">}</p>  <p class="MsoNormal" style="margin-bottom: 6pt;"><strong>3</strong><strong><span style="font-family: 宋体;" lang="ZH-CN">、依赖注入</span> </strong></p>        <p class="MsoNormal" style="margin-bottom: 6pt; text-indent: 21pt;">&nbsp;<span style="font-family: 宋体;" lang="ZH-CN">依赖注入（</span>Dependency Injection<span style="font-family: 宋体;" lang="ZH-CN">）是一个漂亮的隐喻。依赖关系就像是被注入的液体，我们可以在任何时候将依赖关系注入到模块中，而不只限于在编译时绑定。既然这种依赖关系是通过注入的方式完成，就意味着我们可以随时更新，因为注入的液体与模块并无直接关联。实现依赖注入的前提是面向接口编程，而辅助的技术则是利用反射技术。</span></p>  <p class="MsoNormal" style="margin-bottom: 6pt; text-indent: 21pt;"><span style="font-family: 宋体;" lang="ZH-CN">依赖注入是目前大多数轻量级</span>IoC<span style="font-family: 宋体;" lang="ZH-CN">（控制反转，</span>Inversion of Control<span style="font-family: 宋体;" lang="ZH-CN">）容器用于解除外部服务与容器服务之间依赖关系的一把利刃。首先，容器服务包含了外部服务接口的定义。然后，依赖注入通过使用一个专门的装配器对象，提供外部服务的具体实现，并其赋值给对应的容器服务对象。</span>Martin Fowler<span style="font-family: 宋体;" lang="ZH-CN">将依赖注入的形式分为三种：构造函数注入（</span>Constructor Injection<span style="font-family: 宋体;" lang="ZH-CN">）、设置方法注入（</span>Setter Injection<span style="font-family: 宋体;" lang="ZH-CN">）和接口注入（</span>Interface Injection<span style="font-family: 宋体;" lang="ZH-CN">）。其中，接口注入通过定义接口约束的方式实现依赖注入，会给容器带来设计的限制。而构造函数注入与设置方式注入则表现了产生依赖的两个连接点：构造函数与属性。如果构造函数参数或属性对象的类型为抽象的接口类型，则产生具体依赖的源头在于具体对象的创建。将创建具体对象的职责转移到</span>IoC<span style="font-family: 宋体;" lang="ZH-CN">容器，就可以在运行时为构造函数参数或属性对象传递依赖。</span></p>  <p class="MsoNormal" style="margin-bottom: 6pt; text-indent: 21pt;"><span style="font-family: 宋体;" lang="ZH-CN">目前，实现了依赖注入的轻量级容器已经应用在许多框架产品中，如</span>Java<span style="font-family: 宋体;" lang="ZH-CN">平台下的</span>Spring<span style="font-family: 宋体;" lang="ZH-CN">、</span>PicoContainer<span style="font-family: 宋体;" lang="ZH-CN">等。在</span>.NET<span style="font-family: 宋体;" lang="ZH-CN">平台下，常见的依赖注入框架包括</span>AutoFac<span style="font-family: 宋体;" lang="ZH-CN">，</span>Ninject<span style="font-family: 宋体;" lang="ZH-CN">，</span>Spring.NET<span style="font-family: 宋体;" lang="ZH-CN">，</span>StructureMap<span style="font-family: 宋体;" lang="ZH-CN">和</span>Windsor<span style="font-family: 宋体;" lang="ZH-CN">等。</span></p>  <p class="MsoNormal" style="margin-bottom: 6pt; text-indent: 21pt;"><span style="font-family: 宋体;" lang="ZH-CN">以</span>Ninject<span style="font-family: 宋体;" lang="ZH-CN">框架为例，我们可以定义这样的</span>Order<span style="font-family: 宋体;" lang="ZH-CN">类：</span></p>  <p class="a1">public class Order</p>  <p class="a1">{</p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp; </span>private IOrderStrategy m_strategy;</p>  <p class="a1"></p>  <p>&nbsp;</p>  <p>&nbsp;</p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp; </span>public Order(IOrderStrategy strategy)</p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp; </span>{</p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>m_strategy = strategy;</p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp; </span>}</p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp; </span>public void Insert(OrderInfo order)</p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp; </span>{</p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>m_strategy.Insert(order);</p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp; </span>}</p>  <p class="a1">}</p>  <p class="MsoNormal" style="margin-bottom: 6pt; text-indent: 21pt;"><span style="font-family: 宋体;" lang="ZH-CN">然后，我们需要自定义一个</span>OrderModule<span style="font-family: 宋体;" lang="ZH-CN">类，它派生自</span>Ninject.Core.StandardModule<span style="font-family: 宋体;" lang="ZH-CN">类。这是</span>Ninject<span style="font-family: 宋体;" lang="ZH-CN">实现依赖注入的一个特色，它抛弃了传统的</span>xml<span style="font-family: 宋体;" lang="ZH-CN">映射文件，而是利用类型绑定的方式，并根据要创建的具体对象分组建立对应的</span>Module<span style="font-family: 宋体;" lang="ZH-CN">类。注意，它不同于之前的解耦方法，因为它对业务逻辑代码没有造成任何侵略与污染。如上定义的</span>Order<span style="font-family: 宋体;" lang="ZH-CN">类，保留了领域对象的本来面貌。使得领域层的开发人员可以专心致志着力于业务逻辑的实现。</span>OrderModule<span style="font-family: 宋体;" lang="ZH-CN">类的定义如下所示：</span></p>        <p>using Ninject.Core; <br></p>  <p class="a1">public class OrderModule:StandardModule</p>  <p class="a1">{</p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp; </span>public override void Load()</p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp; </span>{</p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Bind&lt;IOrderStrategy&gt;().To&lt;OrderSynchronous&gt;();</p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp; </span>}</p>  <p class="a1">}</p>  <p class="MsoNormal" style="margin-bottom: 6pt; text-indent: 21pt;"><span style="font-family: 宋体;" lang="ZH-CN">客户端调用的代码可以通过</span>Ninject<span style="font-family: 宋体;" lang="ZH-CN">提供的</span>IKernel<span style="font-family: 宋体;" lang="ZH-CN">对象获得</span>Order<span style="font-family: 宋体;" lang="ZH-CN">对象：</span></p>  <p class="a1">OrderModule module = new OrderModule();</p>      <p>IKernel kernal = new StandardKernel(module); <br></p>  <p>&nbsp;</p>  <p class="a1">Order order = kernal.Get&lt;Order&gt;();</p>  <p class="a1">order.Insert(new OrderInfo());</p>  <p class="MsoNormal" style="margin-bottom: 6pt;"><strong>4</strong><strong><span style="font-family: 宋体;" lang="ZH-CN">、惯例优于配置</span> </strong></p>        <p class="MsoNormal" style="margin-bottom: 6pt; text-indent: 21pt;">&nbsp;<span style="font-family: 宋体;" lang="ZH-CN">使用配置文件固然可以解除与具体对象之间的依赖，然而，它带来的良好可扩展性，却是以牺牲系统的可维护性乃至于可靠性为代价的。配置文件很难管理，尤其是在配置信息相对较多的情况下。不管是集中管理还是分散管理，都存在一些与生俱来的缺陷。如果采用集中管理，则配置文件过大，既影响性能，也不能很好地展现配置信息的分类与层次。在</span>.NET<span style="font-family: 宋体;" lang="ZH-CN">中，虽然可以利用</span>&lt;section&gt;&lt;/section&gt;<span style="font-family: 宋体;" lang="ZH-CN">对配置文件进行分节，但终究不够直观。采用分散管理，则不同大小的配置文件千头万绪，既会给维护者带来管理的障碍，也不利于部署与使用。使用配置文件尤其不便于调试。开发环境提供的编译期检查，对于配置文件只能是“望洋兴叹”。所谓“差之毫厘，谬以千里”，小小的一个配置项错误，可能会造成难以弥补的巨大损失。为了弥补这些缺陷，许多产品或框架都提供了专门的配置或管理工具，使用直观的</span>UI<span style="font-family: 宋体;" lang="ZH-CN">界面对配置文件进行操作，但繁杂的配置项仍然有可能让使用者望而却步。</span></p>  <p class="MsoNormal" style="margin-bottom: 6pt; text-indent: 21pt;"><span style="font-family: 宋体;" lang="ZH-CN">惯例优于配置（</span>Convention over Configuration<span style="font-family: 宋体;" lang="ZH-CN">）来源于</span>Ruby On Rails<span style="font-family: 宋体;" lang="ZH-CN">框架的设计理念，也被认为是</span>Rails<span style="font-family: 宋体;" lang="ZH-CN">大获成功的关键因素之一。这里所谓的惯例，可以理解为框架对编程的一些约束，我们可以根据实现制订的默认规则，通过反射技术完成对象的创建，对象的协作，甚至是应用程序的组装。例如在</span>Rails<span style="font-family: 宋体;" lang="ZH-CN">中对</span>MVC<span style="font-family: 宋体;" lang="ZH-CN">模式的实现中，就事先确立了</span>Model<span style="font-family: 宋体;" lang="ZH-CN">、</span>View<span style="font-family: 宋体;" lang="ZH-CN">和</span>Controller<span style="font-family: 宋体;" lang="ZH-CN">的目录结构与命名规范。在这种情况下，我们不需要对元数据进行任何配置。</span>ASP.NET MVC<span style="font-family: 宋体;" lang="ZH-CN">框架同样采纳了惯例优于配置的思想。采用惯例，虽然在一定程度上损失了系统的灵活性，带来的却是良好的可维护性。同时，它仍然可以解除系统与具体对象之间的强耦合关系。</span></p>  <p class="MsoNormal" style="margin-bottom: 6pt; text-indent: 21pt;"><span style="font-family: 宋体;" lang="ZH-CN">惯例优于配置的技术并不是非常适合于本文中的订单策略示例。不过，在</span>.NET<span style="font-family: 宋体;" lang="ZH-CN">框架中，有关</span>WebRequest<span style="font-family: 宋体;" lang="ZH-CN">对象的创建，却可以改用惯例优于配置的思想来实现。图</span>2<span style="font-family: 宋体;" lang="ZH-CN">是</span>WebRequest<span style="font-family: 宋体;" lang="ZH-CN">对象的继承体系：</span></p>  <p class="MsoNormal" style="margin-bottom: 6pt; text-indent: 21pt; text-align: center;" align="center"><a target="_top" href="http://images.cnblogs.com/cnblogs_com/wayfarer/WindowsLiveWriter/dc7ddaef4aa8_1247B/image_5.png"><img title="image" style="border-width: 0px; display: inline;" alt="image" src="image_thumb_1.png" border="0" height="243" width="278"></a> </p>  <p class="MsoNormal" style="margin-bottom: 6pt; text-indent: 21pt; text-align: center;" align="center"><span style="font-family: 宋体;" lang="ZH-CN">图</span>2 WebRequest<span style="font-family: 宋体;" lang="ZH-CN">的类结构</span></p>  <p class="MsoNormal" style="margin-bottom: 6pt; text-indent: 21pt;"><span style="font-family: 宋体;" lang="ZH-CN">在</span>.NET<span style="font-family: 宋体;" lang="ZH-CN">框架中，创建一个</span>WebRequest<span style="font-family: 宋体;" lang="ZH-CN">实例的方法是调用</span>WebRequest<span style="font-family: 宋体;" lang="ZH-CN">的静态方法</span>Create()</p>  <p class="a1"><span>WebRequest myRequest = WebRequest.Create("<a href="http://www.agiledon.com/" class="smarterwiki-linkify">http://www.agiledon.com</a>");</span></p>  <p class="a3" style="margin: 6pt 0in;"><span style="font-family: 宋体;" lang="ZH-CN">由于，传入的</span>Uri<span style="font-family: 宋体;" lang="ZH-CN">地址其前缀为</span>"http"<span style="font-family: 宋体;" lang="ZH-CN">，因此创建的</span>myRequest<span style="font-family: 宋体;" lang="ZH-CN">对象应该为</span>HttpWebRequest<span style="font-family: 宋体;" lang="ZH-CN">具体对象。如果需要根据不同的</span>Request<span style="font-family: 宋体;" lang="ZH-CN">协议，扩展不同的</span>WebRequest<span style="font-family: 宋体;" lang="ZH-CN">对象，就需要引入一些设计技巧，来解除与具体对象创建的依赖。</span>.NET<span style="font-family: 宋体;" lang="ZH-CN">框架的实现能够达到这样的目的，但非常复杂，这里不提。我想要介绍的是如何利用惯例优于配置来实现</span>WebRequest<span style="font-family: 宋体;" lang="ZH-CN">对象的扩展。利用“惯例优于配置”的思想有一个前提，就是我们要对</span>WebRequest<span style="font-family: 宋体;" lang="ZH-CN">对象的命名规范进行惯例约束。例如，我们规定所有的</span>WebRequest<span style="font-family: 宋体;" lang="ZH-CN">子类对象均由协议名加上“</span>WebRequest<span style="font-family: 宋体;" lang="ZH-CN">”后缀构成。通过解析传入的</span>Uri<span style="font-family: 宋体;" lang="ZH-CN">，可以获得传输协议的名称，之后将它与“</span>WebRequest<span style="font-family: 宋体;" lang="ZH-CN">”连接起来，获得</span>WebRequest<span style="font-family: 宋体;" lang="ZH-CN">子类对象的类名，再利用反射技术创建该对象。在</span>WebRequest<span style="font-family: 宋体;" lang="ZH-CN">类中定义如下的</span>Create()<span style="font-family: 宋体;" lang="ZH-CN">静态方法：</span></p>  <p class="a1">public static WebRequest Create(Uri requestUri) </p>  <p class="a1">{</p>  <p class="a1"><span>&nbsp;&nbsp; </span>if (requestUri == null)</p>  <p class="a1"><span>&nbsp;&nbsp; </span>{</p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp; </span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>throw new ArgumentNullException("requestUri");</p>  <p class="a1"><span>&nbsp;&nbsp; </span>}</p>  <p class="a1"><span>&nbsp;&nbsp; </span>string prefix = requestUri.Scheme.ToLower();</p>  <p class="a1" style="text-indent: 0in;"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>if (prefix == null)</p>  <p class="a1"><span>&nbsp;&nbsp; </span>{</p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp; </span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>throw new ArgumentNullException("requestUri");</p>  <p class="a1"><span>&nbsp;&nbsp; </span>}</p>  <p class="a1"><span>&nbsp;&nbsp; </span>if (prefix.Contains(""))</p>  <p class="a1"><span>&nbsp;&nbsp; </span>{</p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>prefix = prefix.Replace(".","");</p>  <p class="a1"><span>&nbsp;&nbsp; </span>}</p>  <p class="a1"><span>&nbsp;&nbsp; </span>StringBuilder typeName = new StringBuilder();</p>  <p class="a1"><span>&nbsp;&nbsp; </span>typeName.Append("System.Net.");</p>  <p class="a1"><span>&nbsp;&nbsp; </span>typeName.Append(prefix.Substring(0,1).ToUpper());</p>  <p class="a1"><span>&nbsp;&nbsp; </span>typeName.Append(prefix.ToLower().Substring(1,prefix.Length - 1));</p>      <p><span>&nbsp;&nbsp; </span>typeName.Append("WebRequest"); <br></p>  <p>&nbsp;</p>  <p class="a1"><span>&nbsp;&nbsp; </span>return (WebRequest)Activitor.CreateInstance(</p>  <p class="a1"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>System.Type.GetType(typeName));</p>  <p class="a1">}</p>  <p class="MsoNormal" style="margin-bottom: 6pt; text-indent: 21pt;"><span style="font-family: 宋体;" lang="ZH-CN">只要</span>WebRequest<span style="font-family: 宋体;" lang="ZH-CN">的子类对象能够遵循我们的惯例，即该类的类型名符合事先制订的规范，改进后的</span>Create()<span style="font-family: 宋体;" lang="ZH-CN">方法就能够运行良好。以新增</span>Tcp<span style="font-family: 宋体;" lang="ZH-CN">协议的</span>WebRequest<span style="font-family: 宋体;" lang="ZH-CN">对象为例。该协议的</span>Schema<span style="font-family: 宋体;" lang="ZH-CN">为“</span>net.tcp<span style="font-family: 宋体;" lang="ZH-CN">”，因此其类名必须为“</span>NettcpWebRequest<span style="font-family: 宋体;" lang="ZH-CN">”，并放在“</span>System.Net<span style="font-family: 宋体;" lang="ZH-CN">”命名空间下。如果客户端调用</span>WebRequest.Create()<span style="font-family: 宋体;" lang="ZH-CN">方法，并传入“</span><span>net.tcp://<a href="http://www.agiledon.com/" class="smarterwiki-linkify">www.agiledon.com</a></span><span style="font-family: 宋体;" lang="ZH-CN">”值，则</span>Create()<span style="font-family: 宋体;" lang="ZH-CN">方法就会对该</span>Uri<span style="font-family: 宋体;" lang="ZH-CN">地址进行解析，获得完整的类型名为“</span>System.Net.NettcpWebRequest<span style="font-family: 宋体;" lang="ZH-CN">”，然后，利用反射技术创建该对象。采用“惯例优于配置”的方式，可以极大地简化工厂方法的实现代码，抛弃了繁琐的设计理念，具有非常灵活的扩展性以及良好的代码可读性。或许，唯一的遗憾是由于反射技术带来的性能损耗。</span></p>  <p class="MsoNormal" style="margin-bottom: 6pt; text-indent: 21pt;"><span style="font-family: 宋体;" lang="ZH-CN">利用抽象的方式封装变化，固然是应对需求变化的王道，但它也仅仅能解除调用者与被调用者之间的耦合关系。只要还涉及具体对象的创建，即使引入了创建型模式，例如</span>Factory Method<span style="font-family: 宋体;" lang="ZH-CN">模式，具体工厂对象的创建依然是必不可少的。不要小看这一点点麻烦，需知“千里之堤，溃于蚁穴”，牵一发而动全身，小麻烦可能会酿成大灾难。对于那些业已被封装变化的对象，我们还应该学会利用诸如“依赖注入”、“表驱动法”等技术，彻底解除两者之间的耦合；至于选择何种技术，则需要根据具体的应用场景做出判断。当然，模块或对象解耦的重要前提，则源于封装变化，要求我们针对接口编程，而不是实现。这也是</span>GOF<span style="font-family: 宋体;" lang="ZH-CN">提出的面向对象设计原则。</span></p>
<div id="digg_block">
<div id="div_digg">										
	<div class="diggit" onclick="DiggIt(1600467,819,1)"> 
		<span class="diggnum" id="digg_count_1600467">12</span>
	</div>
	<div class="buryit" onclick="DiggIt(1600467,819,2)"> 
		<span class="burynum" id="bury_count_1600467">0</span>
	</div>
	<div class="clear"></div>
	<span style="display: none;" id="span_isdigged_1600467">0</span>	
	<div class="diggword" id="digg_word_1600467">(请您对文章做出评价)</div>	
</div>
</div>
<div class="clear"></div>
<div id="post_next_prev">
<a href="http://www.cnblogs.com/wayfarer/archive/2009/11/05/1596954.html">« </a> 上一篇：<a href="http://www.cnblogs.com/wayfarer/archive/2009/11/05/1596954.html" title="发布于2009-11-05 21:20">依赖之殇</a><br>
<a href="http://www.cnblogs.com/wayfarer/archive/2009/11/11/1601360.html">» </a> 下一篇：<a href="http://www.cnblogs.com/wayfarer/archive/2009/11/11/1601360.html" title="发布于2009-11-11 22:18">在Scrum中实施敏捷建模</a><br>
</div>







</div>
		<p class="postfoot">
			posted on 2009-11-10 20:55 <a href="http://www.cnblogs.com/wayfarer/">张逸</a> 阅读(2283) <a href="#commentform">评论(11)</a> &nbsp;<a href="http://www.cnblogs.com/wayfarer/admin/EditPosts.aspx?postid=1600467">编辑</a> <a href="http://www.cnblogs.com/wayfarer/AddToFavorite.aspx?id=1600467">收藏</a> <a href="#" onclick="PutInWz();return false;">网摘</a>  所属分类: <a href="http://www.cnblogs.com/wayfarer/category/14834.html">Design &amp; Pattern</a>
		</p>
	</div>
	<img src="1600467.html" height="1" width="1">
	
<!--
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
<rdf:Description
rdf:about="http://www.cnblogs.com/wayfarer/archive/2009/11/10/1600467.html"
dc:identifier="http://www.cnblogs.com/wayfarer/archive/2009/11/10/1600467.html"
dc:title=""
trackback:ping="http://www.cnblogs.com/wayfarer/services/trackbacks/1600467.aspx" />
</rdf:RDF>
-->

	<a name="pagedcomment"></a>
<a name="评论">
</a>




				
			</div>
			<div id="rightmenu">
				
					
<h3>导航</h3>
<ul>
<li><a id="MyLinks1_HomeLink" href="http://www.cnblogs.com/">博客园</a></li>
<li><a id="MyLinks1_MyHomeLink" href="http://www.cnblogs.com/wayfarer/">首页</a></li>
<li><a id="MyLinks1_NewPostLink" href="http://www.cnblogs.com/wayfarer/admin/EditPosts.aspx?opt=1">新随笔</a></li>
<li><a id="MyLinks1_ContactLink" accesskey="9" href="http://space.cnblogs.com/msg/send/%e5%bc%a0%e9%80%b8">联系</a></li>
<li><a id="MyLinks1_Syndication" href="http://www.cnblogs.com/wayfarer/rss">订阅</a><a id="MyLinks1_XMLLink" href="http://www.cnblogs.com/wayfarer/rss"><img src="xml.gif" alt="订阅" style="border-width: 0px;"></a></li>
<li><a id="MyLinks1_Admin" href="http://www.cnblogs.com/wayfarer/admin/EditPosts.aspx">管理</a></li>
</ul>
					
<h3>公告</h3>
<div class="newsItem">
	我的个人主页：<br>
<a href="http://www.agiledon.com/"><img src="logo.png" alt="logo.gif" border="0" height="78" width="162"></a>
<a href="http://twitter.com/agiledon"><img src="twitter.png"></a><br>

<strong>我的著作与译作</strong>
<p>
<a href="http://www.dangdang.com/zhuanti2006/4742.shtml">《软件设计精要与模式》</a></p>
<p>
<a href="http://www.china-pub.com/38123" target="_top">《WCF服务编程》</a></p>

<ins style="border: medium none ; margin: 0pt; padding: 0pt; display: inline-table; height: 200px; position: relative; visibility: visible; width: 200px;"><ins style="border: medium none ; margin: 0pt; padding: 0pt; display: block; height: 200px; position: relative; visibility: visible; width: 200px;"><iframe allowtransparency="true" hspace="0" id="google_ads_frame4" marginheight="0" marginwidth="0" name="google_ads_frame" src="index_2.html" style="left: 0pt; position: absolute; top: 0pt;" vspace="0" scrolling="no" frameborder="0" height="200" width="200"></iframe></ins></ins>
<p><a href="https://mvp.support.microsoft.com/profile=6C136C2B-30CF-4350-9C52-4BC1B564F251"><img alt="MVP_Horizontal_BlueOnly.png" src="mvp_horizontal_blueonly.png" border="0" height="74" width="182"></a></p>
<div align="left"><!-- Start of StatCounter Code -->From 03-03-2006<br>
<strong>Counter:</strong> <a href="http://www.statcounter.com/" target="_top"><img alt="site stats" src="counter.php" border="0"></a></div>
<div id="profile_block"><a href="http://home.cnblogs.com/wayfarer/" target="_top">我的主页</a>&nbsp; <a href="http://home.cnblogs.com/wayfarer/detail/" target="_top">个人资料</a><br><a href="http://home.cnblogs.com/wayfarer/ing/" target="_top">我的闪存</a>&nbsp; <a href="http://space.cnblogs.com/msg/send/%e5%bc%a0%e9%80%b8" target="_top">发短消息</a></div>
</div>					
					
					
					

<div class="mySearch">
<h3 class="catListTitle">搜索</h3>
<div class="div_my_zzk"><input value="" id="q" onkeydown="return zzk_go_enter(event);" class="input_my_zzk" type="text">&nbsp;<input onclick="zzk_go()" value="找找看" id="btnZzk" class="btn_my_zzk" type="button"></div>
</div>
<h3>常用链接</h3>
<ul>

		<li><a id="SingleColumn1_ctl02_rptMainLinks_ctl00_lnkLinkItem" href="http://www.cnblogs.com/wayfarer/MyPosts.html">我的随笔</a></li>
	
		<li><a id="SingleColumn1_ctl02_rptMainLinks_ctl01_lnkLinkItem" href="http://home.cnblogs.com/wayfarer/">我的空间</a></li>
	
		<li><a id="SingleColumn1_ctl02_rptMainLinks_ctl02_lnkLinkItem" href="http://space.cnblogs.com/msg/recent">我的短信</a></li>
	
		<li><a id="SingleColumn1_ctl02_rptMainLinks_ctl03_lnkLinkItem" href="http://www.cnblogs.com/wayfarer/MyComments.html">我的评论</a></li>
	
<li><a id="itemListLink" onclick="this.blur();WarpClass('itemListLink', 'itemListLin_con');return false;" href="#">更多链接</a></li>
</ul>
<div id="itemListLin_con" style="display: none;">
<ul>
		<li><a id="SingleColumn1_ctl02_repeaterLinks_ctl01_lnkLinkItem" title="我发表过评论的随笔" href="http://www.cnblogs.com/wayfarer/OtherPosts.html">我的参与</a></li>
	
		<li><a id="SingleColumn1_ctl02_repeaterLinks_ctl02_lnkLinkItem" href="http://www.cnblogs.com/wayfarer/MyNews.html">我的新闻</a></li>
	
		<li><a id="SingleColumn1_ctl02_repeaterLinks_ctl03_lnkLinkItem" href="http://www.cnblogs.com/wayfarer/RecentComments.html">最新评论</a></li>
	
		<li><a id="SingleColumn1_ctl02_repeaterLinks_ctl04_lnkLinkItem" href="http://www.cnblogs.com/wayfarer/tag/">我的标签</a></li>
	</ul>
</div>
<h3 class="catListTitle">我参与的团队</h3>
<div class="RecentComment">
	
			<ul style="">
		
			<li>
				<a id="SingleColumn1__1daaec0_TeamList_ctl01_lnkTeam" href="http://team.cnblogs.com/DesignPattern/">Design &amp; Pattern团队(0/0)</a>
			</li>
		
			<li>
				<a id="SingleColumn1__1daaec0_TeamList_ctl02_lnkTeam" href="http://team.cnblogs.com/BJDotNetClub/">北京.NET俱乐部(0/0)</a>
			</li>
		
			<li>
				<a id="SingleColumn1__1daaec0_TeamList_ctl03_lnkTeam" href="http://team.cnblogs.com/chongqing/">重庆.NET俱乐部(0/0)</a>
			</li>
		
			<li>
				<a id="SingleColumn1__1daaec0_TeamList_ctl04_lnkTeam" href="http://team.cnblogs.com/mvpteam/">MVP(微软最有价值专家)团队(0/0)</a>
			</li>
		
			<li>
				<a id="SingleColumn1__1daaec0_TeamList_ctl05_lnkTeam" href="http://team.cnblogs.com/wcfs/">WCF技术研究团队(0/0)</a>
			</li>
		
			<li>
				<a id="SingleColumn1__1daaec0_TeamList_ctl06_lnkTeam" href="http://team.cnblogs.com/softwarehome/">软件开发家园(0/0)</a>
			</li>
		
			</ul>
		
</div>

		<h3>随笔分类<span style="font-size: 11px; font-weight: normal;">(273)</span></h3>
		
				<ul>
			
				<li><a id="SingleColumn1_Categories_CatList_ctl00_LinkList_ctl01_Link" href="http://www.cnblogs.com/wayfarer/category/1092.html">.NET FrameWork(18)</a> <a id="SingleColumn1_Categories_CatList_ctl00_LinkList_ctl01_RssLink" title="Subscribe to .NET FrameWork(18)" href="http://www.cnblogs.com/wayfarer/category/1092.html/rss">(rss)</a></li>
			
				<li><a id="SingleColumn1_Categories_CatList_ctl00_LinkList_ctl02_Link" href="http://www.cnblogs.com/wayfarer/category/1235.html">.NET Remoting(14)</a> <a id="SingleColumn1_Categories_CatList_ctl00_LinkList_ctl02_RssLink" title="Subscribe to .NET Remoting(14)" href="http://www.cnblogs.com/wayfarer/category/1235.html/rss">(rss)</a></li>
			
				<li><a id="SingleColumn1_Categories_CatList_ctl00_LinkList_ctl03_Link" href="http://www.cnblogs.com/wayfarer/category/35983.html">AOP(6)</a> <a id="SingleColumn1_Categories_CatList_ctl00_LinkList_ctl03_RssLink" title="Subscribe to AOP(6)" href="http://www.cnblogs.com/wayfarer/category/35983.html/rss">(rss)</a></li>
			
				<li><a id="SingleColumn1_Categories_CatList_ctl00_LinkList_ctl04_Link" href="http://www.cnblogs.com/wayfarer/category/1236.html">ASP.NET(5)</a> <a id="SingleColumn1_Categories_CatList_ctl00_LinkList_ctl04_RssLink" title="Subscribe to ASP.NET(5)" href="http://www.cnblogs.com/wayfarer/category/1236.html/rss">(rss)</a></li>
			
				<li><a id="SingleColumn1_Categories_CatList_ctl00_LinkList_ctl05_Link" href="http://www.cnblogs.com/wayfarer/category/80097.html">Book(7)</a> <a id="SingleColumn1_Categories_CatList_ctl00_LinkList_ctl05_RssLink" title="Subscribe to Book(7)" href="http://www.cnblogs.com/wayfarer/category/80097.html/rss">(rss)</a></li>
			
				<li><a id="SingleColumn1_Categories_CatList_ctl00_LinkList_ctl06_Link" href="http://www.cnblogs.com/wayfarer/category/1237.html">C# Programming(22)</a> <a id="SingleColumn1_Categories_CatList_ctl00_LinkList_ctl06_RssLink" title="Subscribe to C# Programming(22)" href="http://www.cnblogs.com/wayfarer/category/1237.html/rss">(rss)</a></li>
			
				<li><a id="SingleColumn1_Categories_CatList_ctl00_LinkList_ctl07_Link" href="http://www.cnblogs.com/wayfarer/category/6719.html">DataBase(3)</a> <a id="SingleColumn1_Categories_CatList_ctl00_LinkList_ctl07_RssLink" title="Subscribe to DataBase(3)" href="http://www.cnblogs.com/wayfarer/category/6719.html/rss">(rss)</a></li>
			
				<li><a id="SingleColumn1_Categories_CatList_ctl00_LinkList_ctl08_Link" href="http://www.cnblogs.com/wayfarer/category/14834.html">Design &amp; Pattern(43)</a> <a id="SingleColumn1_Categories_CatList_ctl00_LinkList_ctl08_RssLink" title="Subscribe to Design &amp; Pattern(43)" href="http://www.cnblogs.com/wayfarer/category/14834.html/rss">(rss)</a></li>
			
				<li><a id="SingleColumn1_Categories_CatList_ctl00_LinkList_ctl09_Link" href="http://www.cnblogs.com/wayfarer/category/1239.html">Essay(46)</a> <a id="SingleColumn1_Categories_CatList_ctl00_LinkList_ctl09_RssLink" title="Subscribe to Essay(46)" href="http://www.cnblogs.com/wayfarer/category/1239.html/rss">(rss)</a></li>
			
				<li><a id="SingleColumn1_Categories_CatList_ctl00_LinkList_ctl10_Link" href="http://www.cnblogs.com/wayfarer/category/84415.html">php(1)</a> <a id="SingleColumn1_Categories_CatList_ctl00_LinkList_ctl10_RssLink" title="Subscribe to php(1)" href="http://www.cnblogs.com/wayfarer/category/84415.html/rss">(rss)</a></li>
			
				<li><a id="SingleColumn1_Categories_CatList_ctl00_LinkList_ctl11_Link" href="http://www.cnblogs.com/wayfarer/category/95646.html">Programming WCF Services(16)</a> <a id="SingleColumn1_Categories_CatList_ctl00_LinkList_ctl11_RssLink" title="Subscribe to Programming WCF Services(16)" href="http://www.cnblogs.com/wayfarer/category/95646.html/rss">(rss)</a></li>
			
				<li><a id="SingleColumn1_Categories_CatList_ctl00_LinkList_ctl12_Link" href="http://www.cnblogs.com/wayfarer/category/122419.html">Translation(7)</a> <a id="SingleColumn1_Categories_CatList_ctl00_LinkList_ctl12_RssLink" title="Subscribe to Translation(7)" href="http://www.cnblogs.com/wayfarer/category/122419.html/rss">(rss)</a></li>
			
				<li><a id="SingleColumn1_Categories_CatList_ctl00_LinkList_ctl13_Link" href="http://www.cnblogs.com/wayfarer/category/24807.html">WCF &amp; SOA(21)</a> <a id="SingleColumn1_Categories_CatList_ctl00_LinkList_ctl13_RssLink" title="Subscribe to WCF &amp; SOA(21)" href="http://www.cnblogs.com/wayfarer/category/24807.html/rss">(rss)</a></li>
			
				<li><a id="SingleColumn1_Categories_CatList_ctl00_LinkList_ctl14_Link" href="http://www.cnblogs.com/wayfarer/category/111771.html">WCF Tips(14)</a> <a id="SingleColumn1_Categories_CatList_ctl00_LinkList_ctl14_RssLink" title="Subscribe to WCF Tips(14)" href="http://www.cnblogs.com/wayfarer/category/111771.html/rss">(rss)</a></li>
			
				<li><a id="SingleColumn1_Categories_CatList_ctl00_LinkList_ctl15_Link" href="http://www.cnblogs.com/wayfarer/category/71923.html">博客园图书出版(6)</a> <a id="SingleColumn1_Categories_CatList_ctl00_LinkList_ctl15_RssLink" title="Subscribe to 博客园图书出版(6)" href="http://www.cnblogs.com/wayfarer/category/71923.html/rss">(rss)</a></li>
			
				<li><a id="SingleColumn1_Categories_CatList_ctl00_LinkList_ctl16_Link" href="http://www.cnblogs.com/wayfarer/category/95645.html">软件设计精要与模式(11)</a> <a id="SingleColumn1_Categories_CatList_ctl00_LinkList_ctl16_RssLink" title="Subscribe to 软件设计精要与模式(11)" href="http://www.cnblogs.com/wayfarer/category/95645.html/rss">(rss)</a></li>
			
				<li><a id="SingleColumn1_Categories_CatList_ctl00_LinkList_ctl17_Link" href="http://www.cnblogs.com/wayfarer/category/52160.html">团队公告(13)</a> <a id="SingleColumn1_Categories_CatList_ctl00_LinkList_ctl17_RssLink" title="Subscribe to 团队公告(13)" href="http://www.cnblogs.com/wayfarer/category/52160.html/rss">(rss)</a></li>
			
				<li><a id="SingleColumn1_Categories_CatList_ctl00_LinkList_ctl18_Link" href="http://www.cnblogs.com/wayfarer/category/106653.html">项目管理(16)</a> <a id="SingleColumn1_Categories_CatList_ctl00_LinkList_ctl18_RssLink" title="Subscribe to 项目管理(16)" href="http://www.cnblogs.com/wayfarer/category/106653.html/rss">(rss)</a></li>
			
				<li><a id="SingleColumn1_Categories_CatList_ctl00_LinkList_ctl19_Link" href="http://www.cnblogs.com/wayfarer/category/133955.html">业界时评(4)</a> <a id="SingleColumn1_Categories_CatList_ctl00_LinkList_ctl19_RssLink" title="Subscribe to 业界时评(4)" href="http://www.cnblogs.com/wayfarer/category/133955.html/rss">(rss)</a></li>
			
				</ul>
			
	
		<h3>随笔档案<span style="font-size: 11px; font-weight: normal;">(266)</span></h3>
		
				<ul>
			
				<li><a id="SingleColumn1_Categories_CatList_ctl01_LinkList_ctl01_Link" href="http://www.cnblogs.com/wayfarer/archive/2009/11.html">2009年11月 (4)</a> </li>
			
				<li><a id="SingleColumn1_Categories_CatList_ctl01_LinkList_ctl02_Link" href="http://www.cnblogs.com/wayfarer/archive/2009/10.html">2009年10月 (2)</a> </li>
			
				<li><a id="SingleColumn1_Categories_CatList_ctl01_LinkList_ctl03_Link" href="http://www.cnblogs.com/wayfarer/archive/2009/08.html">2009年8月 (1)</a> </li>
			
				<li><a id="SingleColumn1_Categories_CatList_ctl01_LinkList_ctl04_Link" href="http://www.cnblogs.com/wayfarer/archive/2009/07.html">2009年7月 (1)</a> </li>
			
				<li><a id="SingleColumn1_Categories_CatList_ctl01_LinkList_ctl05_Link" href="http://www.cnblogs.com/wayfarer/archive/2009/06.html">2009年6月 (8)</a> </li>
			
				<li><a id="SingleColumn1_Categories_CatList_ctl01_LinkList_ctl06_Link" href="http://www.cnblogs.com/wayfarer/archive/2009/04.html">2009年4月 (2)</a> </li>
			
				<li><a id="SingleColumn1_Categories_CatList_ctl01_LinkList_ctl07_Link" href="http://www.cnblogs.com/wayfarer/archive/2009/03.html">2009年3月 (7)</a> </li>
			
				<li><a id="SingleColumn1_Categories_CatList_ctl01_LinkList_ctl08_Link" href="http://www.cnblogs.com/wayfarer/archive/2009/02.html">2009年2月 (2)</a> </li>
			
				<li><a id="SingleColumn1_Categories_CatList_ctl01_LinkList_ctl09_Link" href="http://www.cnblogs.com/wayfarer/archive/2008/12.html">2008年12月 (1)</a> </li>
			
				<li><a id="SingleColumn1_Categories_CatList_ctl01_LinkList_ctl10_Link" href="http://www.cnblogs.com/wayfarer/archive/2008/10.html">2008年10月 (1)</a> </li>
			
				<li><a id="SingleColumn1_Categories_CatList_ctl01_LinkList_ctl11_Link" href="http://www.cnblogs.com/wayfarer/archive/2008/09.html">2008年9月 (2)</a> </li>
			
				<li><a id="SingleColumn1_Categories_CatList_ctl01_LinkList_ctl12_Link" href="http://www.cnblogs.com/wayfarer/archive/2008/07.html">2008年7月 (4)</a> </li>
			
				<li><a id="SingleColumn1_Categories_CatList_ctl01_LinkList_ctl13_Link" href="http://www.cnblogs.com/wayfarer/archive/2008/05.html">2008年5月 (2)</a> </li>
			
				<li><a id="SingleColumn1_Categories_CatList_ctl01_LinkList_ctl14_Link" href="http://www.cnblogs.com/wayfarer/archive/2008/04.html">2008年4月 (5)</a> </li>
			
				<li><a id="SingleColumn1_Categories_CatList_ctl01_LinkList_ctl15_Link" href="http://www.cnblogs.com/wayfarer/archive/2008/03.html">2008年3月 (7)</a> </li>
			
				<li><a id="SingleColumn1_Categories_CatList_ctl01_LinkList_ctl16_Link" href="http://www.cnblogs.com/wayfarer/archive/2008/02.html">2008年2月 (7)</a> </li>
			
				<li><a id="SingleColumn1_Categories_CatList_ctl01_LinkList_ctl17_Link" href="http://www.cnblogs.com/wayfarer/archive/2008/01.html">2008年1月 (6)</a> </li>
			
				<li><a id="SingleColumn1_Categories_CatList_ctl01_LinkList_ctl18_Link" href="http://www.cnblogs.com/wayfarer/archive/2007/12.html">2007年12月 (3)</a> </li>
			
				<li><a id="SingleColumn1_Categories_CatList_ctl01_LinkList_ctl19_Link" href="http://www.cnblogs.com/wayfarer/archive/2007/11.html">2007年11月 (7)</a> </li>
			
				<li><a id="SingleColumn1_Categories_CatList_ctl01_LinkList_ctl20_Link" href="http://www.cnblogs.com/wayfarer/archive/2007/10.html">2007年10月 (5)</a> </li>
			
				<li><a id="SingleColumn1_Categories_CatList_ctl01_LinkList_ctl21_Link" href="http://www.cnblogs.com/wayfarer/archive/2007/09.html">2007年9月 (9)</a> </li>
			
				<li><a id="SingleColumn1_Categories_CatList_ctl01_LinkList_ctl22_Link" href="http://www.cnblogs.com/wayfarer/archive/2007/08.html">2007年8月 (3)</a> </li>
			
				<li><a id="SingleColumn1_Categories_CatList_ctl01_LinkList_ctl23_Link" href="http://www.cnblogs.com/wayfarer/archive/2007/06.html">2007年6月 (1)</a> </li>
			
				<li><a id="SingleColumn1_Categories_CatList_ctl01_LinkList_ctl24_Link" href="http://www.cnblogs.com/wayfarer/archive/2007/05.html">2007年5月 (3)</a> </li>
			
				<li><a id="SingleColumn1_Categories_CatList_ctl01_LinkList_ctl25_Link" href="http://www.cnblogs.com/wayfarer/archive/2007/04.html">2007年4月 (4)</a> </li>
			
				<li><a id="SingleColumn1_Categories_CatList_ctl01_LinkList_ctl26_Link" href="http://www.cnblogs.com/wayfarer/archive/2007/03.html">2007年3月 (5)</a> </li>
			
				<li><a id="SingleColumn1_Categories_CatList_ctl01_LinkList_ctl27_Link" href="http://www.cnblogs.com/wayfarer/archive/2007/02.html">2007年2月 (3)</a> </li>
			
				<li><a id="SingleColumn1_Categories_CatList_ctl01_LinkList_ctl28_Link" href="http://www.cnblogs.com/wayfarer/archive/2007/01.html">2007年1月 (1)</a> </li>
			
				<li><a id="SingleColumn1_Categories_CatList_ctl01_LinkList_ctl29_Link" href="http://www.cnblogs.com/wayfarer/archive/2006/12.html">2006年12月 (4)</a> </li>
			
				<li><a id="SingleColumn1_Categories_CatList_ctl01_LinkList_ctl30_Link" href="http://www.cnblogs.com/wayfarer/archive/2006/11.html">2006年11月 (3)</a> </li>
			
				<li><a id="SingleColumn1_Categories_CatList_ctl01_LinkList_ctl31_Link" href="http://www.cnblogs.com/wayfarer/archive/2006/10.html">2006年10月 (2)</a> </li>
			
				<li><a id="SingleColumn1_Categories_CatList_ctl01_LinkList_ctl32_Link" href="http://www.cnblogs.com/wayfarer/archive/2006/09.html">2006年9月 (8)</a> </li>
			
				<li><a id="SingleColumn1_Categories_CatList_ctl01_LinkList_ctl33_Link" href="http://www.cnblogs.com/wayfarer/archive/2006/04.html">2006年4月 (13)</a> </li>
			
				<li><a id="SingleColumn1_Categories_CatList_ctl01_LinkList_ctl34_Link" href="http://www.cnblogs.com/wayfarer/archive/2006/03.html">2006年3月 (6)</a> </li>
			
				<li><a id="SingleColumn1_Categories_CatList_ctl01_LinkList_ctl35_Link" href="http://www.cnblogs.com/wayfarer/archive/2006/02.html">2006年2月 (1)</a> </li>
			
				<li><a id="SingleColumn1_Categories_CatList_ctl01_LinkList_ctl36_Link" href="http://www.cnblogs.com/wayfarer/archive/2006/01.html">2006年1月 (3)</a> </li>
			
				<li><a id="SingleColumn1_Categories_CatList_ctl01_LinkList_ctl37_Link" href="http://www.cnblogs.com/wayfarer/archive/2005/12.html">2005年12月 (1)</a> </li>
			
				<li><a id="SingleColumn1_Categories_CatList_ctl01_LinkList_ctl38_Link" href="http://www.cnblogs.com/wayfarer/archive/2005/11.html">2005年11月 (3)</a> </li>
			
				<li><a id="SingleColumn1_Categories_CatList_ctl01_LinkList_ctl39_Link" href="http://www.cnblogs.com/wayfarer/archive/2005/10.html">2005年10月 (2)</a> </li>
			
				<li><a id="SingleColumn1_Categories_CatList_ctl01_LinkList_ctl40_Link" href="http://www.cnblogs.com/wayfarer/archive/2005/09.html">2005年9月 (4)</a> </li>
			
				<li><a id="SingleColumn1_Categories_CatList_ctl01_LinkList_ctl41_Link" href="http://www.cnblogs.com/wayfarer/archive/2005/08.html">2005年8月 (8)</a> </li>
			
				<li><a id="SingleColumn1_Categories_CatList_ctl01_LinkList_ctl42_Link" href="http://www.cnblogs.com/wayfarer/archive/2005/07.html">2005年7月 (1)</a> </li>
			
				<li><a id="SingleColumn1_Categories_CatList_ctl01_LinkList_ctl43_Link" href="http://www.cnblogs.com/wayfarer/archive/2005/05.html">2005年5月 (1)</a> </li>
			
				<li><a id="SingleColumn1_Categories_CatList_ctl01_LinkList_ctl44_Link" href="http://www.cnblogs.com/wayfarer/archive/2005/04.html">2005年4月 (3)</a> </li>
			
				<li><a id="SingleColumn1_Categories_CatList_ctl01_LinkList_ctl45_Link" href="http://www.cnblogs.com/wayfarer/archive/2005/03.html">2005年3月 (1)</a> </li>
			
				<li><a id="SingleColumn1_Categories_CatList_ctl01_LinkList_ctl46_Link" href="http://www.cnblogs.com/wayfarer/archive/2005/02.html">2005年2月 (1)</a> </li>
			
				<li><a id="SingleColumn1_Categories_CatList_ctl01_LinkList_ctl47_Link" href="http://www.cnblogs.com/wayfarer/archive/2005/01.html">2005年1月 (8)</a> </li>
			
				<li><a id="SingleColumn1_Categories_CatList_ctl01_LinkList_ctl48_Link" href="http://www.cnblogs.com/wayfarer/archive/2004/12.html">2004年12月 (15)</a> </li>
			
				<li><a id="SingleColumn1_Categories_CatList_ctl01_LinkList_ctl49_Link" href="http://www.cnblogs.com/wayfarer/archive/2004/11.html">2004年11月 (7)</a> </li>
			
				<li><a id="SingleColumn1_Categories_CatList_ctl01_LinkList_ctl50_Link" href="http://www.cnblogs.com/wayfarer/archive/2004/10.html">2004年10月 (5)</a> </li>
			
				<li><a id="SingleColumn1_Categories_CatList_ctl01_LinkList_ctl51_Link" href="http://www.cnblogs.com/wayfarer/archive/2004/09.html">2004年9月 (10)</a> </li>
			
				<li><a id="SingleColumn1_Categories_CatList_ctl01_LinkList_ctl52_Link" href="http://www.cnblogs.com/wayfarer/archive/2004/08.html">2004年8月 (9)</a> </li>
			
				<li><a id="SingleColumn1_Categories_CatList_ctl01_LinkList_ctl53_Link" href="http://www.cnblogs.com/wayfarer/archive/2004/07.html">2004年7月 (14)</a> </li>
			
				<li><a id="SingleColumn1_Categories_CatList_ctl01_LinkList_ctl54_Link" href="http://www.cnblogs.com/wayfarer/archive/2004/06.html">2004年6月 (1)</a> </li>
			
				<li><a id="SingleColumn1_Categories_CatList_ctl01_LinkList_ctl55_Link" href="http://www.cnblogs.com/wayfarer/archive/2004/05.html">2004年5月 (3)</a> </li>
			
				<li><a id="SingleColumn1_Categories_CatList_ctl01_LinkList_ctl56_Link" href="http://www.cnblogs.com/wayfarer/archive/2004/04.html">2004年4月 (17)</a> </li>
			
				<li><a id="SingleColumn1_Categories_CatList_ctl01_LinkList_ctl57_Link" href="http://www.cnblogs.com/wayfarer/archive/2004/03.html">2004年3月 (6)</a> </li>
			
				</ul>
			
	

<h3 class="catListTitle">最新随笔</h3>
<div class="RecentComment" id="RecentPosts">
<ul style="">
	
	
			<li><a id="SingleColumn1_ctl04_RecentPostsList_ctl00_RecentPostsList2_ctl00_Hyperlink1" href="http://www.cnblogs.com/wayfarer/archive/2009/11/11/1601360.html">1.&nbsp;在Scrum中实施敏捷建模</a></li>
		
		
	
			<li><a id="SingleColumn1_ctl04_RecentPostsList_ctl01_RecentPostsList2_ctl00_Hyperlink1" href="http://www.cnblogs.com/wayfarer/archive/2009/11/10/1600467.html">2.&nbsp;解除具体依赖的技术</a></li>
		
		
	
			<li><a id="SingleColumn1_ctl04_RecentPostsList_ctl02_RecentPostsList2_ctl00_Hyperlink1" href="http://www.cnblogs.com/wayfarer/archive/2009/11/05/1596954.html">3.&nbsp;依赖之殇</a></li>
		
		
	
			<li><a id="SingleColumn1_ctl04_RecentPostsList_ctl03_RecentPostsList2_ctl00_Hyperlink1" href="http://www.cnblogs.com/wayfarer/archive/2009/11/03/1595555.html">4.&nbsp;虚方法的使用</a></li>
		
		
	
			<li><a id="SingleColumn1_ctl04_RecentPostsList_ctl04_RecentPostsList2_ctl00_Hyperlink1" href="http://www.cnblogs.com/wayfarer/archive/2009/10/28/1591545.html">5.&nbsp;31天速成重构</a></li>
		
	
</ul>
</div>

<h3>积分与排名</h3>
<ul>
	<li>
		积分 -
		1367035
	</li><li>
		排名 -
		15
	</li>
</ul>

<h3 class="catListTitle">最新评论
	<a id="SingleColumn1__a835fb_RSSHyperlink1" href="http://www.cnblogs.com/wayfarer/CommentsRSS.aspx"><img src="xml.gif" style="border-width: 0px;"></a></h3>
<div class="RecentComment" id="RecentComments">
	
			<ul>
		
			<li style="">
				<a id="SingleColumn1__a835fb_CommentList_ctl01_Hyperlink1" href="http://www.cnblogs.com/wayfarer/archive/2008/04/15/1154814.html#1745148">1.&nbsp;Re:博客园为你带来了什么价值</a>
			</li>
			<li style="">
				1 跟踪了技术
跟不上最新的技术，但不能让主流技术把自己落得太远
2 学习了技术
很多人的技术系列，还有博客园的系列专题，非常好。
3 技术资料的储备
4 交流的窗口
这点也非常重要。
			</li>
			<li style="text-align: right; margin-right: 4px;">
				--梅桦</li>
		
			<li style="">
				<a id="SingleColumn1__a835fb_CommentList_ctl02_Hyperlink1" href="http://www.cnblogs.com/wayfarer/archive/2006/04/14/375382.html#1735837">2.&nbsp;Re:PetShop的系统架构设计</a>
			</li>
			<li style="">
				erretryrtytrytrytry
			</li>
			<li style="text-align: right; margin-right: 4px;">
				--rrtyrt</li>
		
			<li style="">
				<a id="SingleColumn1__a835fb_CommentList_ctl03_Hyperlink1" href="http://www.cnblogs.com/wayfarer/archive/2009/11/03/1595555.html#1734451">3.&nbsp;Re:虚方法的使用</a>
			</li>
			<li style="">
				听老师说你的那个封装类的方法写的不错，但是我在你的空间里面找了半天都没有找到，我自己认为我的封装方法写出来的重用性不是很好，所以想像你学习，如果可以的话，可不可以将你的那个封装类发送到我的邮箱：a13...
			</li>
			<li style="text-align: right; margin-right: 4px;">
				--暧—守护</li>
		
			<li style="">
				<a id="SingleColumn1__a835fb_CommentList_ctl04_Hyperlink1" href="http://www.cnblogs.com/wayfarer/archive/2009/11/03/1595555.html#1734445">4.&nbsp;Re:虚方法的使用</a>
			</li>
			<li style="">
				问下，你的那个封装类的方法在那个地方放着的啊？？？
			</li>
			<li style="text-align: right; margin-right: 4px;">
				--暧—守护</li>
		
			<li style="">
				<a id="SingleColumn1__a835fb_CommentList_ctl05_Hyperlink1" href="http://www.cnblogs.com/wayfarer/archive/2009/11/11/1601360.html#1731648">5.&nbsp;Re:在Scrum中实施敏捷建模</a>
			</li>
			<li style="">
				说明，有网友zhou提出，我在文中写到：“Scrum并没有提供核心的价值观”，是不正确的。他提出，Ken Schwaber和Mike Beedle合著的《Agile Software Developm...
			</li>
			<li style="text-align: right; margin-right: 4px;">
				--张逸</li>
		
			</ul>
		
</div>

<h3 class="catListTitle">阅读排行榜</h3>
<div class="RecentComment" id="TopViewPosts"> 
	
			<ul style="">
		
			<li>
				<a id="SingleColumn1_ctl07_TopList_ctl01_Hyperlink1" href="http://www.cnblogs.com/wayfarer/archive/2004/07/30/28723.html">1.&nbsp;Microsoft .Net Remoting系列专题之一:.Net Remoting基础篇 (77504)</a>
			</li>
		
			<li>
				<a id="SingleColumn1_ctl07_TopList_ctl02_Hyperlink1" href="http://www.cnblogs.com/wayfarer/archive/2004/04/21/6779.html">2.&nbsp;automation服务器不能创建对象(65897)</a>
			</li>
		
			<li>
				<a id="SingleColumn1_ctl07_TopList_ctl03_Hyperlink1" href="http://www.cnblogs.com/wayfarer/archive/2006/04/14/375382.html">3.&nbsp;PetShop的系统架构设计(65104)</a>
			</li>
		
			<li>
				<a id="SingleColumn1_ctl07_TopList_ctl04_Hyperlink1" href="http://www.cnblogs.com/wayfarer/archive/2004/04/12/5852.html">4.&nbsp;考察数据结构——第二部分：队列、堆栈和哈希表[译](23289)</a>
			</li>
		
			<li>
				<a id="SingleColumn1_ctl07_TopList_ctl05_Hyperlink1" href="http://www.cnblogs.com/wayfarer/archive/2004/08/05/30437.html">5.&nbsp;Microsoft .Net Remoting系列专题之二：Marshal、Disconnect与生命周期以及跟踪服务(21531)</a>
			</li>
		
			</ul>
		
</div>

<h3 class="catListTitle">评论排行榜</h3>
<div class="RecentComment" id="TopCommentsPosts">
	
			<ul style="">
		
			<li>
				<a id="SingleColumn1_ctl08_TopList_ctl01_Hyperlink1" href="http://www.cnblogs.com/wayfarer/archive/2004/04/21/6779.html">1.&nbsp;automation服务器不能创建对象(304)</a>
			</li>
		
			<li>
				<a id="SingleColumn1_ctl08_TopList_ctl02_Hyperlink1" href="http://www.cnblogs.com/wayfarer/archive/2004/07/30/28723.html">2.&nbsp;Microsoft .Net Remoting系列专题之一:.Net Remoting基础篇 (154)</a>
			</li>
		
			<li>
				<a id="SingleColumn1_ctl08_TopList_ctl03_Hyperlink1" href="http://www.cnblogs.com/wayfarer/archive/2006/04/14/375382.html">3.&nbsp;PetShop的系统架构设计(87)</a>
			</li>
		
			<li>
				<a id="SingleColumn1_ctl08_TopList_ctl04_Hyperlink1" href="http://www.cnblogs.com/wayfarer/archive/2008/04/15/1154814.html">4.&nbsp;博客园为你带来了什么价值(83)</a>
			</li>
		
			<li>
				<a id="SingleColumn1_ctl08_TopList_ctl05_Hyperlink1" href="http://www.cnblogs.com/wayfarer/archive/2007/04/10/707122.html">5.&nbsp;《软件设计精要与模式》出版(81)</a>
			</li>
		
			</ul>
		
</div>
					
<div id="footer">
	Powered by: 
	<br>
	
	<a id="Footer1_Hyperlink3" name="Hyperlink1" href="http://www.cnblogs.com/" style="font-family: Verdana; font-size: 12px;">博客园</a>
	<br>
	Copyright © 张逸
</div>
				
			</div>			
			
	

    </form>
	
	
      
    
    
    
</body>
</html>
